package com.kds.changzhou.message.inbound;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.XmlUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.w3c.dom.Document;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.util.HashMap;
import java.util.Map;

/**
 * @author 孔德嵩
 */
@Component
@Slf4j
public class InBoundMessageFactory {

    private final Map<String, InBoundMessageHandler> handlers = new HashMap<>();


    static final String DATE_FORMAT = "yyyyMMddHHmmss";
    private final XPath xpath;

    {
        handlers.put(InBoundMessageType.sequence, new SequenceMessageHandler());
        handlers.put(InBoundMessageType.result, new ResultMessageHandler());
        handlers.put(InBoundMessageType.period, new PeriodMessageHandler());
        handlers.put(InBoundMessageType.time, new TimeMessageHandler());
        xpath = XPathFactory.newInstance().newXPath();
    }


    public AbstractInboundMessage buildInboundMessage(String xml) throws XPathExpressionException {

        Document document = XmlUtil.parseXml(xml);

        String expression = "/root/common/type/text()";
        String type = (String) xpath.evaluate(expression, document, XPathConstants.STRING);

        InBoundMessageHandler handler = handlers.get(type);
        if (handler != null) {
            return handler.construct(document);
        } else {

            throw new IllegalArgumentException("接收的报文中，xml的type值无对应Handler,type=" + type);
        }


    }

    public class TimeMessageHandler implements InBoundMessageHandler {
        @Override
        public AbstractInboundMessage construct(Document document) throws XPathExpressionException {


            String expression = "/root/heart_beat/time/text()";

            String _time = (String) xpath.evaluate(expression, document, XPathConstants.STRING);

            DateTime dateTime = DateUtil.parse(_time, DATE_FORMAT);

            return new TimeMessage(dateTime.toJdkDate());
        }
    }


    public class PeriodMessageHandler implements InBoundMessageHandler {

        @Override
        public AbstractInboundMessage construct(Document document) throws XPathExpressionException {

            String expression = "/root/config/period/text()";

            Double period = (Double) xpath.evaluate(expression, document, XPathConstants.NUMBER);


            return new PeriodMessage(period);
        }
    }

    public class SequenceMessageHandler implements InBoundMessageHandler {

        @Override
        public AbstractInboundMessage construct(Document document) throws XPathExpressionException {

            String expression = "/root/common/building_id/text()";
            String building_id = (String) xpath.evaluate(expression, document, XPathConstants.STRING);

            expression = "/root/common/gateway_id/text()";
            String gateway_id = (String) xpath.evaluate(expression, document, XPathConstants.STRING);

            expression = "/root/id_validate/sequence/text()";
            String sequence = (String) xpath.evaluate(expression, document, XPathConstants.STRING);

            return new SequenceMessage(building_id, gateway_id, sequence);
        }
    }

    public class ResultMessageHandler implements InBoundMessageHandler {

        @Override
        public AbstractInboundMessage construct(Document document) throws XPathExpressionException {

            String expression = "/root/common/building_id/text()";
            String building_id = (String) xpath.evaluate(expression, document, XPathConstants.STRING);

            expression = "/root/common/gateway_id/text()";
            String gateway_id = (String) xpath.evaluate(expression, document, XPathConstants.STRING);

            expression = "/root/id_validate/result/text()";
            String result = (String) xpath.evaluate(expression, document, XPathConstants.STRING);

            return new ResultMessage(building_id, gateway_id, result);
        }
    }


    public static void main(String[] args) {

        DateTime dateTime = DateUtil.parse("20231211181331", "yyyyMMddHHmmss");
        System.out.println(dateTime);
    }
}
